package robocup.component.infotypes;

import java.util.EnumMap;
import java.util.Vector;

import robocup.component.ControllerNumbers.TEAM;
import robocup.component.ControllerNumbers.VIEW_ANGLE;
//import robocup.component.ControllerNumbers.VIEW_QUALITY;
import robocup.component.actions.Action;

/**
 * A SenseBodyInfo represents the information that can be "felt" by the players.
 * This is for instance his speed, or his stamina, and also the executed actions
 * (counter), which are important for detecting holes and clashes.
 */
public class SenseBodyInfo
    extends Info
    implements Cloneable {

  /**
   * The current view-quality of the player. This is one of HIGH or LOW.
   */
//  protected VIEW_QUALITY                  viewQuality;

  /**
   * The current view-angle of the player. This is either NARROW, NORMAL or
   * WIDE.
   */
  protected VIEW_ANGLE                    viewWidth;

  /**
   * The current stamina of the agent.
   */
  protected double                        stamina;

  /**
   * The players current effort value.
   */
  protected double                        effort;

  /**
   * The players felt speed(-length).
   */
  protected double                        speed;

  /**
   * The players felt speed-direction.
   */
  protected double                        speedDir;

  /**
   * The neck-angle of the player. This is important for position determination,
   * because all seen objects are relative to that angle.
   */
  protected double                        neckAngle;

  /**
   * The number of cycles, the arm can't be redirected to another point.
   */
  protected int                           armMoveable;

  /**
   * The number of cycles, the arm will stay at the point without refreshing the
   * point-action.
   */
  protected int                           armExpires;

  /**
   * The distance to the point, the arm is directed to.
   */
  protected double                        armDist;

  /**
   * The direction to the point, the arm is directed to.
   */
  protected double                        armDir;

  /**
   * The team, to which an attention is set on.
   */
  protected TEAM                          focusTeam;

  /**
   * The number of the player, to whom the attention is set on (attentionto).
   */
  protected int                           focusNumber;

  /**
   * The number of cycles, the agent can't move due to tackling.
   */
  protected int                           tackleExpires;

  /**
   * The counter for all executed actions.
   */
  protected EnumMap<Action.TYPE, Integer> counter = new EnumMap<Action.TYPE, Integer>(
                                                      Action.TYPE.class);

  /**
   * A list containing the actions sent last.
   */
  private Vector<Action>                  lastSentActions;

  /**
   * Stores, if the player collided with an object
   */
  private boolean collisionWithPlayer = false;

  private boolean collisionWithBall = false;

  /**
   * Constructor without any values: all data has to be set with setter-methods
   */
  public SenseBodyInfo() {

    super(0);
    this.infoType = Info.TYPE_SENSE;
  }

  /**
   * A sense-body info, which is frequently received each cycle from the server,
   * containing all agent-specific data
   * 
   * @param cycle -
   *          the time, when the message was received
   * @param viewQuality -
   *          his view-quality (HIGH or LOW)
   * @param viewAngle -
   *          his view-angle (NARROW, NORMAL or WIDE)
   * @param stamina -
   *          the current stamina
   * @param effort -
   *          the current effort
   * @param speed -
   *          the current speed
   * @param speedDir -
   *          the direction of the speed
   * @param neckAngle -
   *          the neck-angle
   * @param kickCount -
   *          how often was a kick-action executed
   * @param dashCount -
   *          how often was a dash-action executed
   * @param turnCount -
   *          how often was a turn-action executed
   * @param sayCount -
   *          how often was a say-action executed
   * @param turnNeckCount -
   *          how often was a turnNeck-action executed
   * @param catchCount -
   *          how often was a catch-action executed
   * @param moveCount -
   *          how often was a move-action executed
   * @param changeViewCount -
   *          how often was a changeViewMode-action executed
   * @param armMoveable -
   *          is the arm movable (pointTo)
   * @param armExpires -
   *          how long does a current pointTo lasts at least
   * @param armDist -
   *          the distance to the target point, the agent is pointing to
   * @param armDir -
   *          the direction of the target point, the agent is pointing to
   * @param focusTeam -
   *          attention of which team (attentionTo)
   * @param focusNumber -
   *          attention on which player (unum - attentionTo)
   * @param focusCount -
   *          how often was an attentionTo executed
   * @param tackleExpires -
   *          how long does a current tackle-dead lasts at least
   * @param tackleCount -
   *          how often was a tackle-action executed
   */
  public SenseBodyInfo(
      final int cycle,
//      final VIEW_QUALITY viewQuality,
      final VIEW_ANGLE viewAngle,
      final double stamina,
      final double effort,
      final double speed,
      final double speedDir,
      final double neckAngle,
      final int kickCount,
      final int dashCount,
      final int turnCount,
      final int sayCount,
      final int turnNeckCount,
      final int catchCount,
      final int moveCount,
      final int changeViewCount,
      final int armMoveable,
      final int armExpires,
      final double armDist,
      final double armDir,
      final TEAM focusTeam,
      final int focusNumber,
      final int focusCount,
      final int tackleExpires,
      final int tackleCount) {

    super(cycle);
//    this.viewQuality = viewQuality;
    this.viewWidth = viewAngle;
    this.stamina = stamina;
    this.effort = effort;
    this.speed = speed;
    this.speedDir = speedDir;
    this.neckAngle = neckAngle;
    this.armMoveable = armMoveable;
    this.armExpires = armExpires;
    this.armDist = armDist;
    this.armDir = armDir;
    this.focusTeam = focusTeam;
    this.focusNumber = focusNumber;
    this.tackleExpires = tackleExpires;
    this.setCounter(Action.TYPE.ATTENTIONTO, focusCount);
    this.setCounter(Action.TYPE.TACKLE, tackleCount);
    this.setCounter(Action.TYPE.KICK, kickCount);
    this.setCounter(Action.TYPE.DASH, dashCount);
    this.setCounter(Action.TYPE.TURN, turnCount);
    this.setCounter(Action.TYPE.SAY, sayCount);
    this.setCounter(Action.TYPE.TURN_NECK, turnNeckCount);
    this.setCounter(Action.TYPE.CATCH_BALL, catchCount);
    this.setCounter(Action.TYPE.MOVE, moveCount);
    this.setCounter(Action.TYPE.CHANGE_VIEW_MODE, changeViewCount);
    this.cycle = cycle;

    this.infoType = Info.TYPE_SENSE;
  }

  /**
   * @return Returns the list of actions, which were sent in the last cycle.
   */
  public Vector<Action> getLastSentActions() {

    return this.lastSentActions;
  }

  /**
   * Sets a new list of actions to the info-obejct, which were sent last cycle.
   * 
   * @param lastSentActions
   */
  public void setLastSentActions(final Vector<Action> lastSentActions) {

    this.lastSentActions = lastSentActions;
  }

  /**
   * Returns teh amount of executed actions by type.
   * 
   * @param type -
   *          the type of the action
   * @return the amount of &lt;type&gt;-actions, which were successfully
   *         executed.
   */
  public int getCount(final Action.TYPE type) {

    return this.counter.get(type).intValue();
  }

  /**
   * Sets the amount of executed actions for the given type.
   * 
   * @param type -
   *          the type of the action
   * @param count -
   *          the counter for that action
   */
  public void setCounter(final Action.TYPE type,
      final int count) {

    this.counter.put(type, Integer.valueOf(count));
  }

  /**
   * @return Returns the cycle.
   */
  @Override
  public int getCycle() {

    return this.cycle;
  }

  /**
   * @return Returns the effort.
   */
  public double getEffort() {

    return this.effort;
  }

  /**
   * @return Returns the headAngle.
   */
  public double getNeckAngle() {

    return this.neckAngle;
  }

  /**
   * @return Returns the speed.
   */
  public double getSpeed() {

    return this.speed;
  }

  /**
   * @return Returns the speedDir.
   */
  public double getSpeedDir() {

    return this.speedDir;
  }

  /**
   * @return Returns the stamina.
   */
  public double getStamina() {

    return this.stamina;
  }

  /**
   * @return Returns the viewQuality.
   */
//  public VIEW_QUALITY getViewQuality() {
//
//    return this.viewQuality;
//  }

  /**
   * @return Returns the viewWidth.
   */
  public VIEW_ANGLE getViewWidth() {

    return this.viewWidth;
  }

  /**
   * Sets a new view-quality for this info-object.
   * 
   * @param viewQuality
   */
//  public void setViewQuality(final VIEW_QUALITY viewQuality) {
//
//    this.viewQuality = viewQuality;
//  }

  /**
   * Sets a new view-width for this info-object.
   * 
   * @param viewWidth
   */
  public void setViewWidth(final VIEW_ANGLE viewWidth) {

    this.viewWidth = viewWidth;
  }

  /**
   * Sets a new stamina value for this info-object.
   * 
   * @param stamina
   */
  public void setStamina(final double stamina) {

    this.stamina = stamina;
  }

  /**
   * Sets a new effort value for this info-object.
   * 
   * @param effort
   */
  public void setEffort(final double effort) {

    this.effort = effort;
  }

  /**
   * Sets a new speed value for this info-object.
   * 
   * @param speed
   */
  public void setSpeed(final double speed) {

    this.speed = speed;
  }

  /**
   * Sets a new speed-direction value for this info-object.
   * 
   * @param speedDir
   */
  public void setSpeedDir(final double speedDir) {

    this.speedDir = speedDir;
  }

  /**
   * Sets a new neck-angle value for this info-object.
   * 
   * @param headAngle
   */
  public void setNeckAngle(final double headAngle) {

    this.neckAngle = headAngle;
  }

  /**
   * Sets a new cycle value for this info-object.
   * 
   * @param cycle
   */
  @Override
  public synchronized void setCycle(final int cycle) {

    this.cycle = cycle;
  }

  /**
   * @return Returns the arm-direction.
   */
  public double getArmDir() {

    return this.armDir;
  }

  /**
   * Sets a new arm-direction value for this info-object.
   * 
   * @param armDir
   */
  public void setArmDir(final double armDir) {

    this.armDir = armDir;
  }

  /**
   * @return Returns the distance of the point, the arm is pointing to.
   */
  public double getArmDist() {

    return this.armDist;
  }

  /**
   * Sets a new arm pointing-distance value for this info-object.
   * 
   * @param armDist
   */
  public void setArmDist(final double armDist) {

    this.armDist = armDist;
  }

  /**
   * @return Returns the number of cycles, in which the arm expires in pointing
   *         to the currect position, without refreshing the command.
   */
  public int getArmExpires() {

    return this.armExpires;
  }

  /**
   * Sets a new arm-expires value for this info-object.
   * 
   * @param armExpires
   */
  public void setArmExpires(final int armExpires) {

    this.armExpires = armExpires;
  }

  /**
   * @return Returns the number of cycles, in which the arm is movable again.
   */
  public int getArmMoveable() {

    return this.armMoveable;
  }

  /**
   * Sets a new arm-movable value for this info-object.
   * 
   * @param armMoveable
   */
  public void setArmMoveable(final int armMoveable) {

    this.armMoveable = armMoveable;
  }

  /**
   * @return Returns the number of cycles, in which the player can move again
   *         after tackling.
   */
  public int getTackleExpires() {

    return this.tackleExpires;
  }

  /**
   * Sets the number of cycles for this info-object, in which the player can
   * move again after tackling.
   * 
   * @param tackleExpires
   */
  public void setTackleExpires(final int tackleExpires) {

    this.tackleExpires = tackleExpires;
  }

  /**
   * @return Returns the number of the player, the attention is set on.
   */
  public int getFocusNumber() {

    return this.focusNumber;
  }

  /**
   * Sets a new value for the number, the player is setting his attention to.
   * 
   * @param focusNumber
   */
  public void setFocusNumber(final int focusNumber) {

    this.focusNumber = focusNumber;
  }

  /**
   * @return Returns the TEAM (WE or OPPONENT), the attention is set on.
   */
  public TEAM getFocusTeam() {

    return this.focusTeam;
  }

  /**
   * Sets the team, to which the attention is set to.
   * 
   * @param focusTeam
   */
  public void setFocusTeam(final TEAM focusTeam) {

    this.focusTeam = focusTeam;
  }

  /**
   * @return Returns the sum of all action (DASH, KICK, TURN, CATCH_BALL, MOVE,
   *         TACKLE), which were executed up to now.
   */
  public int getMainActionsCountSum() {

    return this.counter.get(Action.TYPE.KICK) + this.counter
        .get(Action.TYPE.DASH) + this.counter.get(Action.TYPE.TURN) + this.counter
        .get(Action.TYPE.CATCH_BALL) + this.counter.get(Action.TYPE.MOVE) + this.counter
        .get(Action.TYPE.TACKLE);
  }

  /**
   * @return Returns a debug-string for that info-object.
   */
  @Override
  public String toString() {

    String str = "";
    str += "\n DIRECTION: " + this.getArmDir();
    str += "\n DISTANCE : " + this.getArmDist();
    str += "\n EXPIRES  : " + this.getArmExpires();
    str += "\n MOVABLE  : " + this.getArmMoveable();
    return str;
  }

  
  public void setCollisionWithPlayer(boolean bplayer) {
	this.collisionWithPlayer = bplayer;
  }

  public void setCollisionWithBall(boolean bball) {
	this.collisionWithBall = bball;
  }

public boolean isCollisionWithPlayer() {
	return collisionWithPlayer;
}

public boolean isCollisionWithBall() {
	return collisionWithBall;
}

}
